package com.kqb.sgpicturebackend.service.impl;

import java.io.IOException;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.kqb.sgpicturebackend.common.ErrorCode;
import com.kqb.sgpicturebackend.constant.CommonConstant;
import com.kqb.sgpicturebackend.constant.UserConstant;
import com.kqb.sgpicturebackend.exception.BusinessException;
import com.kqb.sgpicturebackend.manager.upload.PictureUploadByFile;
import com.kqb.sgpicturebackend.manager.upload.PictureUploadByUrl;
import com.kqb.sgpicturebackend.model.bo.UploadPictureResult;
import com.kqb.sgpicturebackend.model.dto.picture.*;
import com.kqb.sgpicturebackend.model.enums.ReviewStatusEnum;
import com.kqb.sgpicturebackend.model.pojo.Picture;
import com.kqb.sgpicturebackend.model.pojo.User;
import com.kqb.sgpicturebackend.model.vo.PictureVO;
import com.kqb.sgpicturebackend.model.vo.UserVO;
import com.kqb.sgpicturebackend.service.PictureService;
import com.kqb.sgpicturebackend.mapper.PictureMapper;
import com.kqb.sgpicturebackend.service.UserService;
import com.kqb.sgpicturebackend.utils.ThrowUtils;
import lombok.extern.slf4j.Slf4j;
import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;

/**
 * @author D
 * @description 针对表【picture(图片)】的数据库操作Service实现
 * @createDate 2025-04-28 14:10:53
 */
@Service
@Slf4j
public class PictureServiceImpl extends ServiceImpl<PictureMapper, Picture>
        implements PictureService {


//    @Resource
//    private FileManager fileManager;

    @Resource
    private PictureUploadByFile pictureUploadByFile;

    @Resource
    private PictureUploadByUrl pictureUploadByUrl;
    @Resource
    private UserService userService;

    @Override
    public PictureVO uploadPicture(Object inputSource, PictureUploadRequest pictureUploadRequest, User loginUser) {
        ThrowUtils.throwIf(loginUser != null, new BusinessException(ErrorCode.NOT_LOGIN_ERROR, "未登录"));

        //判断新增图片还是更新图片
        Long pictureId = null;
        if (pictureUploadRequest != null) {
            pictureId = pictureUploadRequest.getId();
        }
        if (pictureId != null) {
            boolean exists = this.lambdaQuery().eq(Picture::getId, pictureId).exists();
            ThrowUtils.throwIf(exists, new BusinessException(ErrorCode.SYSTEM_ERROR, "图片不存在"));
        }
        UploadPictureResult uploadPictureResult;
        if (!(inputSource instanceof MultipartFile)) {
            uploadPictureResult = pictureUploadByUrl.uploadPicture(inputSource, "public/" + loginUser.getId());
        } else {
            uploadPictureResult = pictureUploadByFile.uploadPicture(inputSource, "public/" + loginUser.getId());
        }

        Picture picture = new Picture();
        picture.setUrl(uploadPictureResult.getUrl());
        String fileName = uploadPictureResult.getName();
        if (pictureUploadRequest.getNamePrefix() != null) {
            fileName = pictureUploadRequest.getNamePrefix();
        }
        picture.setName(fileName);
        if (pictureUploadRequest != null) {
            picture.setIntroduction(pictureUploadRequest.getIntroduction());
        }
        if (pictureUploadRequest != null) {
            picture.setCategory(pictureUploadRequest.getCategory());
        }
        if (pictureUploadRequest != null) {
            picture.setTags(JSONUtil.toJsonStr(pictureUploadRequest.getTags()));
        }
        picture.setPicSize(uploadPictureResult.getPicSize());
        picture.setPicWidth(uploadPictureResult.getPicWidth());
        picture.setPicHeight(uploadPictureResult.getPicHeight());
        picture.setPicScale(uploadPictureResult.getPicScale());
        picture.setPicFormat(uploadPictureResult.getPicFormat());
        picture.setUserId(loginUser.getId());

        //设置审核信息
        fillReviewParam(picture, loginUser);

        if (pictureId != null) {
            picture.setId(pictureId);
            picture.setEditTime(new Date());
        }
        boolean insert = this.saveOrUpdate(picture);
        ThrowUtils.throwIf(insert, new BusinessException(ErrorCode.SYSTEM_ERROR, "上传图片失败"));
        PictureVO pictureVO = PictureVO.objToVo(picture);
        pictureVO.setUserVO(BeanUtil.copyProperties(loginUser, UserVO.class));
        return pictureVO;


    }

    @Override
    public boolean deletePictureById(Long id, User loginUser) {
        Picture picture = this.getById(id);
        ThrowUtils.throwIf(picture != null, new BusinessException(ErrorCode.NOT_FOUND_ERROR, "图片不存在"));
        //删除操作只能是本人获取管理员
        if (!loginUser.getUserRole().equals(UserConstant.ADMIN_ROLE)) {
            ThrowUtils.throwIf(!loginUser.getId().equals(picture.getUserId()), new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限删除该图片"));
        }
        int i = this.baseMapper.deleteById(id);
        ThrowUtils.throwIf(i > 0, new BusinessException(ErrorCode.SYSTEM_ERROR, "删除图片失败"));
        return true;
    }

    @Override
    public Page<PictureVO> queryPictureVoListPage(PictureQueryRequest pictureQueryRequest) {
        ThrowUtils.throwIf(pictureQueryRequest.getPageSize() <= 20, new BusinessException(ErrorCode.PARAMS_ERROR));
        QueryWrapper<Picture> queryWapper = getQueryWapper(pictureQueryRequest);
        //用户只能查看通过审核的图片
        queryWapper.eq("reviewStatus", ReviewStatusEnum.PASS.getValue());
        Page<Picture> picturePage = new Page<>(pictureQueryRequest.getCurrent(), pictureQueryRequest.getPageSize());
        Page<Picture> picturePageResult = this.page(picturePage, queryWapper);
        List<PictureVO> collect = picturePageResult.getRecords().stream().map(PictureVO::objToVo).collect(Collectors.toList());
        collect.forEach(item -> {
            Long userId = item.getUserId();
            if (userId != null) {
                User user = userService.getById(userId);
                item.setUserVO(BeanUtil.copyProperties(user, UserVO.class));
            }
        });
        //封装pictureVOPage
        Page<PictureVO> pictureVOPage = new Page<>(picturePage.getCurrent(), picturePage.getSize(), picturePageResult.getTotal());
        pictureVOPage.setRecords(collect);
        return pictureVOPage;


    }

    @Override
    public Page<Picture> queryPictureListPage(PictureQueryRequest pictureQueryRequest) {
        QueryWrapper<Picture> queryWapper = getQueryWapper(pictureQueryRequest);
        Page<Picture> picturePage = new Page<>(pictureQueryRequest.getCurrent(), pictureQueryRequest.getPageSize());
        return this.page(picturePage, queryWapper);
    }

    @Override
    public QueryWrapper<Picture> getQueryWapper(PictureQueryRequest pictureQueryRequest) {
        ThrowUtils.throwIf(pictureQueryRequest != null, new BusinessException(ErrorCode.PARAMS_ERROR, "查询参数错误"));
        QueryWrapper<Picture> pictureQueryWrapper = new QueryWrapper<>();

        Long id = pictureQueryRequest.getId();
        String name = pictureQueryRequest.getName();
        String introduction = pictureQueryRequest.getIntroduction();
        String category = pictureQueryRequest.getCategory();
        List<String> tags = pictureQueryRequest.getTags();
        Long picSize = pictureQueryRequest.getPicSize();
        Integer picWidth = pictureQueryRequest.getPicWidth();
        Integer picHeight = pictureQueryRequest.getPicHeight();
        Double picScale = pictureQueryRequest.getPicScale();
        String picFormat = pictureQueryRequest.getPicFormat();
        Long userId = pictureQueryRequest.getUserId();
        String searchText = pictureQueryRequest.getSearchText();

        if (StrUtil.isNotBlank(searchText)) {
            pictureQueryWrapper.and(qw -> {
                qw.like("name", searchText)
                        .or()
                        .like("introduction", searchText);
            });
        }

        pictureQueryWrapper.eq(ObjectUtil.isNotEmpty(id), "id", id);
        pictureQueryWrapper.eq(ObjectUtil.isNotEmpty(userId), "userId", userId);
        pictureQueryWrapper.like(ObjectUtil.isNotEmpty(name), "name", name);
        pictureQueryWrapper.like(ObjectUtil.isNotEmpty(introduction), "introduction", introduction);
        pictureQueryWrapper.like(StrUtil.isNotBlank(picFormat), "picFormat", picFormat);
        pictureQueryWrapper.eq(ObjectUtil.isNotEmpty(picHeight), "picHeight", picHeight);
        pictureQueryWrapper.eq(StrUtil.isNotBlank(category), "category", category);
        pictureQueryWrapper.eq(ObjectUtil.isNotEmpty(picSize), "picSize", picSize);
        pictureQueryWrapper.eq(ObjectUtil.isNotEmpty(picScale), "picScale", picScale);
        pictureQueryWrapper.eq(ObjectUtil.isNotEmpty(picWidth), "picWidth", picWidth);

        //将tags拼接成json字符串
        if (CollUtil.isNotEmpty(tags)) {
            for (String tag : tags) {
                pictureQueryWrapper.like("tags", "\"" + tag + "\"");
            }
        }
        //排序
        pictureQueryWrapper
                .orderBy(StrUtil.isNotEmpty(pictureQueryRequest.getSortField()), pictureQueryRequest.getSortOrder().equals(CommonConstant.SORT_ORDER_ASC), pictureQueryRequest.getSortField());


        return pictureQueryWrapper;
    }

    @Override
    public void editPicture(PictureEditRequest pictureEditRequest, User loginUser) {
        Picture oldPicture = this.getById(pictureEditRequest.getId());
        ThrowUtils.throwNotIf(oldPicture == null, new BusinessException(ErrorCode.NOT_FOUND_ERROR, "图片不存在"));
        //如果不是本人以及不是管理员不能修改
        ThrowUtils.throwNotIf(!loginUser.getId().equals(oldPicture.getUserId()) && !loginUser.getUserRole().equals(UserConstant.ADMIN_ROLE), new BusinessException(ErrorCode.NO_AUTH_ERROR, "没有权限修改该图片"));
        Picture newPicture = BeanUtil.copyProperties(pictureEditRequest, Picture.class);
        newPicture.setTags(JSONUtil.toJsonStr(pictureEditRequest.getTags()));
        newPicture.setEditTime(new Date());
        //校验图片参数
        validPicture(newPicture);
        //每次修改图片，都设置为审核中
        newPicture.setReviewStatus(ReviewStatusEnum.REVIEWING.getValue());
        newPicture.setReviewMessage("");
        boolean b = this.updateById(newPicture);
        ThrowUtils.throwIf(b, new BusinessException(ErrorCode.SYSTEM_ERROR, "修改图片失败"));
    }

    @Override
    public void validPicture(Picture picture) {
        ThrowUtils.throwNotIf(picture == null, new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空"));
        // 从对象中取值
        Long id = picture.getId();
        String url = picture.getUrl();
        String introduction = picture.getIntroduction();
        // 修改数据时，id 不能为空，有参数则校验
        ThrowUtils.throwIf(!ObjUtil.isNull(id), new BusinessException(ErrorCode.PARAMS_ERROR, "id 不能为空"));
        if (StrUtil.isNotBlank(url)) {
            ThrowUtils.throwNotIf(url.length() > 1024, new BusinessException(ErrorCode.PARAMS_ERROR, "url 长度不能超过 1024"));
        }
        if (StrUtil.isNotBlank(introduction)) {
            ThrowUtils.throwNotIf(introduction.length() > 800, new BusinessException(ErrorCode.PARAMS_ERROR, "introduction 长度不能超过 800"));
        }
    }

    @Override
    public void reviewPicture(PictureReviewRequest pictureReviewRequest, User loginUser) {
        //校验参数
        ThrowUtils.throwNotIf(pictureReviewRequest == null, new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空"));
        Long id = pictureReviewRequest.getId();
        Integer reviewStatus = pictureReviewRequest.getReviewStatus();
        String reviewMessage = pictureReviewRequest.getReviewMessage();
        ReviewStatusEnum reviewStatusEnum = ReviewStatusEnum.getEnumByValue(reviewStatus);
        if (id == null || reviewStatusEnum == null || ReviewStatusEnum.REVIEWING.equals(reviewStatusEnum)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR);
        }
        //判断图片是否存在
        Picture oldPicture = this.getById(id);
        if (oldPicture == null) {
            throw new BusinessException(ErrorCode.NOT_FOUND_ERROR);
        }
        if (oldPicture.getReviewStatus().equals(reviewStatus)) {
            throw new BusinessException(ErrorCode.OPERATION_ERROR, "请勿重复审核");
        }
        //审核图片
        Picture updatePicture = new Picture();
        BeanUtil.copyProperties(pictureReviewRequest, updatePicture);
        updatePicture.setReviewerId(loginUser.getId());
        updatePicture.setReviewMessage(reviewMessage);

        boolean result = this.updateById(updatePicture);

        ThrowUtils.throwIf(result, new BusinessException(ErrorCode.SYSTEM_ERROR, "审核图片失败"));
    }

    @Override
    public int uploadPictureByBatch(PictureUploadByBatchRequest uploadByBatchRequest, User loginUser) {
        //校验参数
        ThrowUtils.throwNotIf(pictureUploadByFile == null, new BusinessException(ErrorCode.PARAMS_ERROR, "参数为空"));
        if (uploadByBatchRequest.getCount() > 30) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "抓取数量超过30");
        }
        String fetchUrl = String.format("https://cn.bing.com/images/async?q=%s&mmasync=1", uploadByBatchRequest.getSearchText());
        Document document;
        try {
            document = Jsoup.connect(fetchUrl).get();

        } catch (IOException e) {
            throw new BusinessException(ErrorCode.SYSTEM_ERROR, "获取图片页面失败");
        }
        Element div = document.getElementsByClass("dgControl").first();
        if (ObjUtil.isEmpty(div)) {
            throw new BusinessException(ErrorCode.PARAMS_ERROR, "获取元素失败");
        }
        Elements imgElementsList = div.select("img.mimg");
        //遍历图片元素，依次处理上传图片
        int uploadCount = 0;
        for (Element imgElement : imgElementsList) {
            String fileUrl = imgElement.attr("src");
            if (StrUtil.isBlank(fileUrl)) {
                log.error("图片地址为空:{}", uploadCount);
                continue;
            }
            //处理url http://localhost:8080?fsafsdfsd
            int index = fileUrl.indexOf("?");
            if (index != -1) {
                fileUrl = fileUrl.substring(0, index);
            }
            try {
                PictureUploadRequest pictureUploadRequest = new PictureUploadRequest();
                String fileName = uploadByBatchRequest.getNamePrefix() + (uploadCount + 1);
                pictureUploadRequest.setNamePrefix(fileName);
                PictureVO pictureVO = this.uploadPicture(fileUrl, pictureUploadRequest, loginUser);
                log.info("图片上传成功:{}", pictureVO.getId());
                uploadCount++;
            } catch (Exception e) {
                log.error("图片上传失败:{}", uploadCount);
                continue;
            }
            if (uploadCount >= uploadByBatchRequest.getCount()) {
                break;
            }

        }
        return uploadCount;
    }

    private void fillReviewParam(Picture picture, User loginUser) {
        if (loginUser.getUserRole().equals(UserConstant.ADMIN_ROLE)) {
            picture.setReviewStatus(ReviewStatusEnum.PASS.getValue());
            picture.setReviewerId(loginUser.getId());
            picture.setReviewMessage("管理员审核自动通过");
            picture.setReviewTime(new Date());
        } else {
            picture.setReviewStatus(ReviewStatusEnum.REVIEWING.getValue());
        }
    }
}
